Skip to content

fix(m365): exclude disabled guest users from entra_users_mfa_capable#11002

Merged
HugoPBrito merged 4 commits into
masterfrom
fix/m365-entra-users-mfa-capable-disabled-guests
May 12, 2026
Merged

fix(m365): exclude disabled guest users from entra_users_mfa_capable#11002
HugoPBrito merged 4 commits into
masterfrom
fix/m365-entra-users-mfa-capable-disabled-guests

Conversation

@HugoPBrito

Copy link
Copy Markdown
Member

Context

Fix #10921

CIS Microsoft 365 Foundations Benchmark recommendation 5.2.3.4 (entra_users_mfa_capable) scopes the control to enabled member users only, but the check was still raising findings for disabled guest accounts. This is a regression of the original fix delivered in #10785, which was validated against synthetic data but did not exercise the EXO Get-User source path used in production tenants.

Description

Microsoft Graph's /users endpoint omits accountEnabled, userType and onPremisesSyncEnabled from the default property set, so they are never populated unless requested explicitly via $select. The previous implementation:

  1. Called await self.client.users.get() without $select, so user.account_enabled and user.user_type arrived as None/missing.
  2. Derived account_enabled solely from the EXO PowerShell Get-User map, which does not return guest accounts at all.

For a disabled guest user this produced account_enabled=True (Pydantic default) and user_type=None, slipping past the if user.user_type == "Guest" or not user.account_enabled filter in entra_users_mfa_capable.py.

This PR:

  • Adds an explicit $select (id, displayName, userType, accountEnabled, onPremisesSyncEnabled) to the Graph users.get() call in Entra._get_users().
  • Uses Microsoft Graph as the source of truth for account_enabled (and continues to use it for user_type).
  • Falls back to the EXO PowerShell Get-User map only when Graph does not return a value, preserving the legacy behaviour for any tenant where the Graph response is missing the property.

Steps to review

  1. Inspect prowler/providers/m365/services/entra/entra_service.py:
    • _get_users now passes a RequestConfiguration with UsersRequestBuilderGetQueryParameters(select=[...]).
    • account_enabled is derived from getattr(user, "account_enabled", None) first, falling back to the EXO user_accounts_status map only when Graph returns None.
  2. Run the targeted tests:
    poetry run pytest tests/providers/m365/services/entra/microsoft365_entra_service_test.py tests/providers/m365/services/entra/entra_users_mfa_capable -v
    New regression: test__get_users_uses_graph_account_enabled_for_disabled_guests proves a disabled guest from Graph (with empty EXO map) is now modelled as account_enabled=False. The pagination test additionally verifies the new $select is sent on every Graph users.get() call.
  3. Confirm prowler/CHANGELOG.md lists the fix under [5.26.0] -> 🐞 Fixed linking issue (Regression) Disabled Guest users should not be included in "5.2.3.4 (L1) Ensure all member users are 'MFA capable'" check #10921.

Checklist

Community Checklist
  • This feature/issue is listed in here or roadmap.prowler.com
  • Is it assigned to me, if not, request it via the issue/feature in here or Prowler Community Slack

SDK/CLI

  • Are there new checks included in this PR? No — bug fix to existing check entra_users_mfa_capable (no permission changes required).

License

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

Microsoft Graph's /users endpoint omits accountEnabled, userType and
onPremisesSyncEnabled from the default property set. Without an explicit
$select these fields were never returned, so the User model fell back to
its Pydantic defaults (account_enabled=True, user_type=None) and the EXO
PowerShell Get-User map was used to derive account_enabled. EXO does not
return guest users at all, which meant disabled guest accounts surfaced
as enabled members and failed the entra_users_mfa_capable check
(CIS 5.2.3.4).

Request the relevant fields via $select and use Graph as the source of
truth for account_enabled and user_type, falling back to the EXO
PowerShell value only when Graph does not return one. Fixes #10921.
@HugoPBrito HugoPBrito requested a review from a team as a code owner May 5, 2026 13:23
@github-actions github-actions Bot added the provider/m365 Issues/PRs related with the M365 provider label May 5, 2026
@github-actions

github-actions Bot commented May 5, 2026

Copy link
Copy Markdown
Contributor

Conflict Markers Resolved

All conflict markers have been successfully resolved in this pull request.

@github-actions

github-actions Bot commented May 5, 2026

Copy link
Copy Markdown
Contributor

✅ All necessary CHANGELOG.md files have been updated.

@codecov

codecov Bot commented May 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.16%. Comparing base (759f7b8) to head (b1a7386).

Additional details and impacted files
@@             Coverage Diff             @@
##           master   #11002       +/-   ##
===========================================
+ Coverage   12.12%   88.16%   +76.03%     
===========================================
  Files         854      131      -723     
  Lines       24838     5550    -19288     
===========================================
+ Hits         3012     4893     +1881     
+ Misses      21826      657    -21169     
Flag Coverage Δ
prowler-py3.10-aws ?
prowler-py3.10-m365 88.16% <100.00%> (?)
prowler-py3.11-aws ?
prowler-py3.11-m365 87.67% <100.00%> (?)
prowler-py3.12-aws ?
prowler-py3.12-m365 88.16% <100.00%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
prowler 88.16% <100.00%> (+76.03%) ⬆️
api ∅ <ø> (∅)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

github-actions Bot commented May 5, 2026

Copy link
Copy Markdown
Contributor

🔒 Container Security Scan

Image: prowler:020837b
Last scan: 2026-05-12 07:39:17 UTC

📊 Vulnerability Summary

Severity Count
🔴 Critical 5
Total 5

5 package(s) affected

⚠️ Action Required

Critical severity vulnerabilities detected. These should be addressed before merging:

  • Review the detailed scan results
  • Update affected packages to patched versions
  • Consider using a different base image if updates are unavailable

📋 Resources:

@HugoPBrito

Copy link
Copy Markdown
Member Author

Please @jacobcsmith let me know if this works for you if possible. I'd really appreciate that.

@jacobcsmith

Copy link
Copy Markdown

I tested on my end and it works as expected 👍

@HugoPBrito

Copy link
Copy Markdown
Member Author

Thank you very much! I didn't see this before. We will merge then.

@HugoPBrito HugoPBrito added the backport-to-v5.26 Backport PR to the v5.26 branch label May 12, 2026
5.26.0 has been released, so the fix moves to a new 5.26.1 patch section.
@HugoPBrito HugoPBrito force-pushed the fix/m365-entra-users-mfa-capable-disabled-guests branch from 1cc5d5a to b1a7386 Compare May 12, 2026 07:29

@pedrooot pedrooot left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔝 🐐

@HugoPBrito HugoPBrito merged commit 1b0e12e into master May 12, 2026
26 checks passed
@HugoPBrito HugoPBrito deleted the fix/m365-entra-users-mfa-capable-disabled-guests branch May 12, 2026 07:35
Comment thread prowler/CHANGELOG.md
@prowler-bot prowler-bot added the was-backported The PR was successfully backported to the target branch label May 12, 2026
@prowler-bot

Copy link
Copy Markdown
Collaborator

💚 All backports created successfully

Status Branch Result
v5.26

Questions ?

Please refer to the Backport tool documentation and see the Github Action logs for details

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport-to-v5.26 Backport PR to the v5.26 branch provider/m365 Issues/PRs related with the M365 provider was-backported The PR was successfully backported to the target branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

(Regression) Disabled Guest users should not be included in "5.2.3.4 (L1) Ensure all member users are 'MFA capable'" check

5 participants